home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyo (Python 2.5) from __future__ import division import os import sys from util import Delegate from util.ffi import cimport from threading import Thread from ctypes import windll, WinError, byref, c_ulonglong from ctypes.wintypes import HANDLE, FILETIME from time import clock, sleep from traceback import print_exc from cStringIO import StringIO from datetime import datetime from common.commandline import where from util.threads import BackgroundThread from logging import getLogger log = getLogger('perfmon') PROCESS_QUERY_INFORMATION = 1024 THREAD_QUERY_INFORMATION = 64 cimport(kernel32 = [ 'GetProcessTimes', 'GetThreadTimes', 'OpenProcess', 'CloseHandle', 'OpenThread']) if getattr(sys, 'DEV', False): NUM_CONSECUTIVE_HIGHS = 5 else: NUM_CONSECUTIVE_HIGHS = 60 TICK_FREQUENCY = 5 PROFILE_TICKS = 15 CPU_THRESHOLD = 0.95 TICKS_PER_SEC = 1e+07 from util.introspect import all_profilers def enable_profilers(): profilers = all_profilers().values() for profiler in profilers: profiler.enable() _log_enabled_profilers(profilers) def disable_profilers(): profilers = all_profilers().values() for profiler in profilers: profiler.disable() _log_enabled_profilers(profilers) def _log_enabled_profilers(profilers): len([] % ([](_[1]), len(profilers))) def profilers_enabled(): return all((lambda .0: for p in .0: p.enabled)(all_profilers().itervalues())) def get_stack_info(): io = StringIO() where(duplicates = True, stream = io) stack_info = io.getvalue() return '\n\n'.join([ datetime.now().isoformat(), stack_info]) class CPUWatch(object): def usage(self, user, kernel): return getattr(self, self.state + '_usage')(user, kernel) def watching_usage(self, user, kernel): self.user = user self.kernel = kernel if user + kernel >= self.threshold: self.count += 1 log.info('cpu usage is high (not profiling yet: %s/%s): %s', self.count, NUM_CONSECUTIVE_HIGHS, user + kernel) if self.count > NUM_CONSECUTIVE_HIGHS: import wx wx.CallAfter(self.prompt_for_profiling) else: self.count = 0 def profiling_usage(self, user, kernel): self.user = user self.kernel = kernel if user + kernel >= self.threshold: log.info('cpu usage is high: %s' % (user + kernel)) self.stack_info.append(get_stack_info()) self.count += 1 if self.count > PROFILE_TICKS: self.disable() self.send_info() else: log.info('cpu usage was low again: %s' % (user + kernel)) log.info('') self.count = 0 self.state = 'watching' def disabled_usage(self, user, kernel): pass def send_info(self): log.info('sending diagnostic information...') Diagnostic = Diagnostic import util.diagnostic import wx try: d = Diagnostic(description = 'CPU usage was too high.') d.prepare_data() if d.do_no_thread_post(): return wx.CallAfter(wx.MessageBox, _('A log of the problem has been sent to digsby.com.\n\nThanks for helping!'), _('Diagnostic Log')) except Exception: print_exc() wx.CallAfter(wx.MessageBox, _('There was an error when submitting the diagnostic log.')) def prompt_for_profiling(self): if self._CPUWatch__in: return None self._CPUWatch__in = True log.info('prompting for profiling info') dev = getattr(sys, 'DEV', False) if profilers_enabled(): self.state = 'profiling' return log.info('profiler is already enabled') import wx if dev or wx.YES == wx.MessageBox(_('Digsby appears to be running slowly.\n\nDo you want to capture diagnostic information and\nsend it to digsby.com?'), _('Digsby CPU Usage'), style = wx.YES_NO | wx.ICON_ERROR): log.info('enabling profiler') enable_profilers() self.count = 0 self.state = 'profiling' else: self.disable() self._CPUWatch__in = False def disable(self): self.state = 'disabled' disable_profilers() self.cpu_monitor.done = True def __init__(self, threshold = CPU_THRESHOLD): if threshold < threshold: pass elif not threshold <= 1: raise ValueError('0 < threshold <= 1') self.state = 'watching' self.threshold = threshold self.count = 0 self.ignore = False self.cpu_monitor = CPUMonitor(self.usage) self.cpu_monitor.start() self._CPUWatch__in = False self.stack_info = [] class CPUMonitor(BackgroundThread): def __init__(self, usage_cb, update_freq_secs = TICK_FREQUENCY): BackgroundThread.__init__(self, name = 'CPUMonitor') self.setDaemon(True) self.done = False self.update_freq_secs = 5 self.perfinfo = ProcessPerfInfo() self.usage_cb = usage_cb def run(self): self.BeforeRun() while not self.done: self.usage_cb(*self.perfinfo.update()) sleep(self.update_freq_secs) self.AfterRun() class PerfInfo(object): __slots__ = [ 'last_update', 'handle', 'creationTime', 'exitTime', 'kernelTime', 'userTime', 'oldKernel', 'oldUser'] def __init__(self): self.last_update = clock() for name in ('creationTime', 'exitTime', 'kernelTime', 'userTime', 'oldKernel', 'oldUser'): setattr(self, name, c_ulonglong()) self.handle = self.get_handle() self.update() def get_handle(self): raise NotImplemented def update(self): if not self.times_func(self.handle, byref(self.creationTime), byref(self.exitTime), byref(self.kernelTime), byref(self.userTime)): raise WinError() now = clock() diff = now - self.last_update userPercent = (self.userTime.value - self.oldUser.value) / TICKS_PER_SEC / diff kernelPercent = (self.kernelTime.value - self.oldKernel.value) / TICKS_PER_SEC / diff self.last_update = now self.oldUser.value = self.userTime.value self.oldKernel.value = self.kernelTime.value return (userPercent, kernelPercent) def __del__(self): CloseHandle(self.handle) class ProcessPerfInfo(PerfInfo): __slots__ = [] def __init__(self): PerfInfo.__init__(self) def get_handle(self): return obtain_process_handle() def times_func(self): return GetProcessTimes times_func = property(times_func) class ThreadPerfInfo(PerfInfo): __slots__ = [ 'thread_id'] def __init__(self, thread_id): self.thread_id = thread_id PerfInfo.__init__(self) def get_handle(self): return obtain_thread_handle(self.thread_id) def times_func(self): return GetThreadTimes times_func = property(times_func) def num_processors(): return os.environ.get('NUMBER_OF_PROCESSORS', 1) def obtain_process_handle(pid = None): handle = None(OpenProcess, PROCESS_QUERY_INFORMATION, False if pid is None else pid) if not handle: raise WinError() return handle def obtain_thread_handle(thread_id): handle = OpenThread(THREAD_QUERY_INFORMATION, False, thread_id) if not handle: raise WinError() return handle def main(): import wx a = wx.PySimpleApp() f = wx.Frame(None) b = wx.Button(f, -1, 'info') def foo(): while True: pass t = Thread(target = foo) cpumonitor = CPUMonitor() cpumonitor.start() def onbutton(e): t.start() b.Bind(wx.EVT_BUTTON, onbutton) f.Show() a.MainLoop() if __name__ == '__main__': main()